package app

import (
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/gogf/gf/util/guid"
	_ "golang.org/x/tools/go/ssa"
	"time"
)

// TMQTTComponent MQTT组件
type TMQTTComponent struct {
	Client           mqtt.Client                //连接对象
	Host             string                     //主机IP
	Port             int                        //主机端口
	User             string                     //用户名
	Password         string                     //密码
	OnConnect        mqtt.OnConnectHandler      //连接事件
	OnConnectionLost mqtt.ConnectionLostHandler //断开连接事件
	OnMessage        mqtt.MessageHandler        //收到消息事件
}

// Close 断开连接
func (mc *TMQTTComponent) Close() {
	mc.Client.Disconnect(1000)
}

// Sub 订阅主题
func (mc *TMQTTComponent) Sub(ATopic string) {
	token := mc.Client.Subscribe(ATopic, 1, nil)
	token.Wait()
}

// Publish 发布消息
func (mc *TMQTTComponent) Publish(ATopic string, APayload string) error {
	token := mc.Client.Publish(ATopic, 0, false, APayload)
	token.Wait()
	return token.Error()
}

// Init 初始化组件
func (mc *TMQTTComponent) Init() error {
	var broker = mc.Host
	var port = mc.Port
	opts := mqtt.NewClientOptions()
	opts.AddBroker(fmt.Sprintf("mqtt://%s:%d", broker, port))
	opts.SetKeepAlive(time.Hour * 24)
	opts.SetPingTimeout(time.Second * 30)
	opts.SetClientID(guid.S())
	opts.SetUsername(mc.User)
	opts.SetPassword(mc.Password)
	opts.SetDefaultPublishHandler(mc.OnMessage)
	opts.OnConnect = mc.OnConnect
	opts.OnConnectionLost = mc.OnConnectionLost
	mc.Client = mqtt.NewClient(opts)
	if token := mc.Client.Connect(); token.Wait() && token.Error() != nil {
		return token.Error()
	} else {
		return nil
	}
}

/*
//初始化MQTT
func InitMQTT(server_ip string, server_port int, server_user string, server_pwd string, server_topic string) {
	var broker = server_ip
	var port = server_port
	opts := mqtt.NewClientOptions()
	opts.AddBroker(fmt.Sprintf("mqtt://%s:%d", broker, port))
	opts.SetKeepAlive(time.Hour * 24)
	opts.SetPingTimeout(time.Second * 30)
	opts.SetClientID(guid.S())
	opts.SetUsername(server_user)
	opts.SetPassword(server_pwd)
	opts.SetDefaultPublishHandler(messagePubHandler)
	opts.OnConnect = connectHandler
	opts.OnConnectionLost = connectLostHandler
	mc = mqtt.NewClient(opts)
	if token := mc.Connect(); token.Wait() && token.Error() != nil {
		panic(token.Error())
	}
	sub(mc, server_topic)
}

//处理消息
var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
	fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic())
	//解析传输指令集，指令集为JSON格式
	//处理FirstBill信息

		if msg.Topic() == "Bill/FirstBill" {
			var mcmd TMqttFirstBill
			err := json.Unmarshal(msg.Payload(), &mcmd)
			fmt.Println("JSON Error", err)
			fmt.Println(mcmd)
			fmt.Println(msg.Topic())
			if err == nil {
				//处理本条TMqttFirstBill消息
				//记录user_cash_bills表的现金支出
				mDir, _ := os.Getwd()
				if mcmd.Status == 3 {
					_, er := g.DB().Insert("user_cash_bills", g.Map{
						"msg_id":      mcmd.Msg_Id,
						"user_id":     mcmd.UserId,
						"open_id":     mcmd.OpenId,
						"merch_id":    mcmd.MerchId,
						"description": "消费支出",
						"cash_out":    mcmd.RealPrice,
						"payway":      mcmd.Payway,
						"extra_data":  mcmd,
						"dir":         mDir + "/" + os.Args[0],
						"ip":          MyIP(),
					})
					fmt.Println("保存 UserCashBills DB Error=", er)
					//记录merch_cash_bills表的现金收入
					_, er = g.DB().Insert("merch_cash_bills", g.Map{
						"msg_id":      mcmd.Msg_Id,
						"user_id":     mcmd.UserId,
						"open_id":     mcmd.OpenId,
						"merch_id":    mcmd.MerchId,
						"description": "顾客消费",
						"cash_in":     mcmd.RealPrice,
						"payway":      mcmd.Payway,
						"extra_data":  mcmd,
						"dir":         mDir + "/" + os.Args[0],
						"ip":          MyIP(),
					})
					fmt.Println("保存 MerchCashBills DB Error=", er)
				}
				//_, er := g.DB().Exec("insert into demo2 (\"Topic\") values (?)", msg.Topic())
			}
		}

}

//订阅主题
func sub(client mqtt.Client, topic string) {
	token := client.Subscribe(topic, 1, nil)
	token.Wait()
	fmt.Printf("Subscribed to topic %s", topic)
}

//发布消息
func publishBefore(client mqtt.Client, command TMqttIntfBefore) string {
	command.SendTime = time.Now()
	j, err := json.Marshal(command)
	if err == nil {
		token := client.Publish(command.Topic, 0, false, string(j))
		token.Wait()
		//time.Sleep(time.Second)
		return ""
	} else {
		return err.Error()
	}
}

func publishAfter(client mqtt.Client, command TMqttIntfAfter) string {
	//command.Msg_Id = guid.S()
	command.SendTime = time.Now()
	j, err := json.Marshal(command)
	if err == nil {
		token := client.Publish(command.Topic, 0, false, string(j))
		token.Wait()
		//time.Sleep(time.Second)
		return ""
	} else {
		return err.Error()
	}
}

func publish(client mqtt.Client, command TMqttFirstBill) string {
	//command.Msg_Id = guid.S()
	command.SendTime = time.Now()
	j, err := json.Marshal(command)
	if err == nil {
		token := client.Publish(command.Topic, 0, false, string(j))
		token.Wait()
		//time.Sleep(time.Second)
		return ""
	} else {
		return err.Error()
	}
}

var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {
	fmt.Println("Connected")
}

var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
	fmt.Printf("Connect lost: %v", err)
	token := mc.Connect()
	token.Wait()
	sub(mc, g.Cfg().GetString("mqtt.broker_topic"))
}
*/
